using DA.AnimGraph;
using OdinSerializer;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;

namespace DA.AnimGraph.Editor {

    internal class AGANode_BlendSpace2D : AGANode_SampleBase, IResourceNode {
        public override AGANodeModelBase modelProperty { set => model = (AGANodeModel_BlendSpace2D)value; get => model; }
        [OdinSerialize] AGANodeModel_BlendSpace2D model;

        public AGANode_BlendSpace2D(AGANodeModelBase model) : base(model) {
        }

        public override int Publish(List<PublishNode> outNodes, AGAPublisher.PublishContext context) {
            var pNode = new BlendSpace2DPNode();
            pNode.uuid = uuid;
            pNode.data = model.Publish(context);
            var index = outNodes.Count;
            outNodes.Add(pNode);
            PublishPerks(pNode, context);
            return index;
        }

        public AUID[] GetResources() {
            return model.GetResources();
        }
        public void ReplaceResourceAUID(Dictionary<AUID, AUID> uuidMapping) {
            model.ReplaceResourceAUID(uuidMapping);
        }
    }


    [ModelOf(typeof(AGANode_BlendSpace2D))]
    internal class AGANodeModel_BlendSpace2D : AGANodeModelBase {

        public List<AGAFieldModel_BlendSpace2DVertex> vertices = new();
        public AGAFieldModel_Vector2Link inputPosition = new();

        public BlendSpace2DNode.SetupData Publish(AGAPublisher.PublishContext context) {
            var clipDescs = new List<ClipLinkDesc>(vertices.Count);
            var triVertices = new List<Vector2>(vertices.Count);
            var clipIds = new List<int>(vertices.Count);

            for (int i = 0; i < vertices.Count; i++) {
                var clipDesc = vertices[i].clip.Publish(context);
                var index = clipDescs.FindIndex(x => x.uuid == clipDesc.uuid);
                if (index < 0) {
                    clipDescs.Add(clipDesc);
                    clipIds.Add(clipDescs.Count - 1);
                } else {
                    clipIds.Add(index);
                }
                triVertices.Add(vertices[i].position);
            }

            var triangulation = new Triangulation();
            triangulation.AddVertices(triVertices, clipIds);
            var setupData = new BlendSpace2DNode.SetupData() {
                clipsDesc = clipDescs.ToArray(),
                positionDesc = inputPosition.Publish(context)
            };
            triangulation.Triangulate();
            triangulation.OutputToData(out setupData.triangulationData);

            return setupData;
        }

        public AUID[] GetResources() {
            return vertices.Select(x => x.clip.clipKey).Where(x => x.isValid).ToArray();
        }
        public void ReplaceResourceAUID(Dictionary<AUID, AUID> uuidMapping) {
            foreach (var p in vertices) {
                if (uuidMapping.TryGetValue(p.clip.clipKey, out var newId)) {
                    p.clip.clipKey = newId;
                }
            }
        }
    }
}
